file: use lstat for file list (instead of stat) to reveal links
authorPaul Donald <[email protected]>
Wed, 11 Jun 2025 21:52:01 +0000 (23:52 +0200)
committerRobert Marko <[email protected]>
Thu, 30 Oct 2025 11:07:04 +0000 (12:07 +0100)
commit11e0bee504c643e94e54ad6b66185a0164842a5c
treee8a872d0f0b86502d8a43a679c4646a362388a5a
parentcfb93f105ca2b5e81c5e489076f38d5786f346ea
file: use lstat for file list (instead of stat) to reveal links

I don't think there was a conscious design choice for stat(), but it is
documented that the 'type' entry using the rpcd file mechanisms can be
'symlink' but this is never the case using stat().

lstat and stat are virtually identical, but that lstat reports that
a symlink entry is a symlink, whereas stat reports that a symlink entry
is a file (the file it points to) and info about the link target
instead.

Someone parsing a directory using stat() would never know about links.

Using lstat, we can see whether an entry is a symlink for no extra cost.
When the file list encounters a link entry, it now includes the element
"target_type" which contains the link target type: "file", "directory"
etc - or "broken" if the link is broken - via one additional stat call.

So when calling e.g.: ubus call file list '{"path":"/etc"}'

instead of:

...
"name": "os-release",
"type": "file",
"size": 610,
"mode": 33188,
"atime": 1749462226,
"mtime": 1749462226,
"ctime": 1749462226,
"inode": 894,
"uid": 0,
"gid": 0
...

We get:

...
"name": "os-release",
"type": "symlink",
"size": 21,
"mode": 41471,
"atime": 1749462226,
"mtime": 1749462226,
"ctime": 1749462226,
"inode": 234,
"uid": 0,
"gid": 0,
"target_type": "file"
...

Moved the type determination out of _rpc_file_add_stat to a new function
_get_stat_type for re-usability in the if (S_ISLNK(s.st_mode)) block.

Tested on: openwrt main

Signed-off-by: Paul Donald <[email protected]>
Tested-by: Eric Fahlgren <[email protected]>
Link: https://github.com/openwrt/rpcd/pull/13
Signed-off-by: Robert Marko <[email protected]>
file.c